#ifndef DISPLAY_LIST_UTILS_H_
#define DISPLAY_LIST_UTILS_H_

class DisplayListsUtils{
	private:
		GLuint dlhandle;
		GLuint dlAxis;
		GLuint dlGrid;
		GLuint dlAxis2DTop;
		GLuint dlAxis2DHeight;

	public:
		void createDisplayLists(){
			dlhandle = glGenLists(3);
			dlAxis=dlhandle+0;
			dlGrid=dlhandle+1;
			dlAxis2DTop=dlhandle+2;
			dlAxis2DHeight=dlhandle+3;

			// Generaci�n de las Display Lists
			glNewList(dlAxis, GL_COMPILE);
				drawAxis();
			glEndList();
			glNewList(dlGrid, GL_COMPILE);
				drawXYGrid();
			glEndList();
			glNewList(dlAxis2DTop, GL_COMPILE);
				drawAxis2DTopView();
			glEndList();
			glNewList(dlAxis2DHeight, GL_COMPILE);
				drawAxis2DHeightView();
			glEndList();
		}

		static void drawAxis(){
			glDisable(GL_LIGHTING);
			glBegin(GL_LINES);
				// X
				glColor3f(1.0, 0.0, 0.0);
				glVertex3f(0.0, 0.0, 0.0);
				glColor3f(0.0, 0.0, 0.0);
				glVertex3f(15.0, 0.0, 0.0);
				// Y
				glColor3f(0.0, 1.0, 0.0);
				glVertex3f(0.0, 0.0, 0.0);
				glColor3f(0.0, 0.0, 0.0);
				glVertex3f(0.0, 15.0, 0.0);
				// Z
				glColor3f(0.0, 0.0, 1.0);
				glVertex3f(0.0, 0.0, 0.0);
				glColor3f(0.0, 0.0, 0.0);
				glVertex3f(0.0, 0.0, 15.0);
			glEnd();
			glEnable(GL_LIGHTING);
		}

		static void drawAxis2DTopView(){
			glDisable(GL_LIGHTING);
			glPushMatrix();
				glTranslatef(0.5f,0.5f,0.0f);
				glBegin(GL_LINES);
					// X
					glColor3f(1.0f, 0.0f, 0.0f);
					glVertex3f(0.0f, 0.0f, 0.0f);
					glVertex3f(0.25f, 0.0f, 0.0f);
					// Y
					glColor3f(0.0f, 1.0f, 0.0f);
					glVertex3f(0.0f, 0.0f, 0.0f);
					glVertex3f(0.0f, 0.25f, 0.0f);
					glEnd();

				glBegin(GL_TRIANGLES);
					// X
					glColor3f(1.0f, 0.0f, 0.0f);
					glVertex3f(0.27f, 0.0f, 0.0f);
					glVertex3f(0.23f, -0.01f, 0.0f);
					glVertex3f(0.23f, 0.01f, 0.0f);

					// Y
					glColor3f(0.0f, 1.0f, 0.0f);
					glVertex3f(0.0f, 0.27f, 0.0f);
					glVertex3f(0.01f, 0.23f, 0.0f);
					glVertex3f(-0.01f, 0.23f, 0.0f);
				glEnd();

				glRasterPos3f(0.05, 0.25, 0.0);
				glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12,'y');
				glRasterPos3f(0.25, 0.05, 0.0);
				glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12,'x');
				glEnable(GL_LIGHTING);
			glPopMatrix();
		}

		static void drawAxis2DHeightView(){
			glDisable(GL_LIGHTING);
			glBegin(GL_LINES);
				// X
				glColor3f(1.0, 0.0, 0.0);
				glVertex3f(0.03, 0.07, 0.0);
				glVertex3f(0.25, 0.07, 0.0);

				// Y
				glColor3f(0.0, 1.0, 0.0);
				glVertex3f(0.07, 0.03, 0.0);
				glVertex3f(0.07, 0.25, 0.0);
			glEnd();
			glBegin(GL_TRIANGLES);
				// X
				glColor3f(1.0, 0.0, 0.0);
				glVertex3f(0.27, 0.07, 0.0);
				glVertex3f(0.23, 0.06, 0.0);
				glVertex3f(0.23, 0.08, 0.0);

				// Y
				glColor3f(0.0, 1.0, 0.0);
				glVertex3f(0.07, 0.27, 0.0);
				glVertex3f(0.06, 0.23, 0.0);
				glVertex3f(0.08, 0.23, 0.0);
			glEnd();

			glRasterPos3f(0.09, 0.25, 0.0);
			glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12,'z');
			glRasterPos3f(0.25, 0.09, 0.0);
			glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12,'u');
			glEnable(GL_LIGHTING);
		}

		static void drawXYGrid(){
			int i;
			glDisable(GL_LIGHTING);
			glColor3f(0.35, 0.15, 0.1);
			glBegin(GL_LINES);
			for(i=-20; i<21; i++)
			{
				glVertex3f(i, -20.0, 0.0);
				glVertex3f(i,  20.0, 0.0);
				glVertex3f(-20.0, i, 0.0);
				glVertex3f( 20.0, i, 0.0);
			}
			glEnd();
			glEnable(GL_LIGHTING);
		}

		static DisplayListsUtils& instance(){
			static DisplayListsUtils instance;
			return instance;
		}

		GLuint getAxisHandle(){
			return this->dlAxis;
		}

		GLuint getGridHandle(){
			return this->dlGrid;
		}

		GLuint getAxis2DTopHandle(){
			return this->dlAxis2DTop;
		}

		GLuint getAxis2DHeightHandle(){
			return this->dlAxis2DHeight;
		}

	private:
		DisplayListsUtils(){
			dlhandle=0;
			dlAxis=0;
			dlGrid=0;
			dlAxis2DTop=0;
			dlAxis2DHeight=0;
		}
		DisplayListsUtils(const DisplayListsUtils& u){}

		void operator=(const DisplayListsUtils& u){}
};

#endif /* DISPLAY_LIST_UTILS_H_ */
